import pygame 
from settings import *
from tile import Tile
from player import Player
from support import *
from random import choice, randint
from weapon import Weapon
from ui import UI
from enemy import Enemy
from particles import AnimationPlayer
from magic import MagicPlayer
from upgrade import Upgrade
from button import Button


class Level:
	def __init__(self):

		#获取当前显示窗口的表面对象 可以使用这个表面对象来绘制游戏内容
		self.display_surface = pygame.display.get_surface()

		#创建两个精灵组，一个是可见的精灵组，一个是障碍物精灵组
		self.visible_sprites = YSortCameraGroup()
		self.obstacle_sprites = pygame.sprite.Group()

		#武器精灵
		self.current_attack = None
		#攻击精灵组
		self.attack_sprites = pygame.sprite.Group()
		#攻击目标精灵组
		self.attackable_sprites = pygame.sprite.Group()

		#调用create_map方法创建地图
		self.create_map()

		#创建UI对象
		self.ui = UI()
		#创建升级对象
		self.upgrade = Upgrade(self.player)
		#是否显示升级界面
		self.game_paused = False

		#创建动画播放器对象
		self.animation_player = AnimationPlayer()
		#创建玩家释放技能对象
		self.magic_player = MagicPlayer(self.animation_player)

		#游戏是否结束
		self.game_over = False
		#创建按钮对象
		self.button = Button("Click to start again", TILESIZE * 5 , TILESIZE * 2)


	def create_map(self):
     
		layouts = {
			'boundary': import_csv_layout('../map/map_FloorBlocks.csv'),
			'grass': import_csv_layout('../map/map_Grass.csv'),
			'object': import_csv_layout('../map/map_Objects.csv'),
			'entities': import_csv_layout('../map/map_Entities.csv')
		}
		graphics = {
			'grass': import_folder('../graphics/grass'),
			'objects': import_folder('../graphics/objects')
		}
  
		for style,layout in layouts.items():
			for row_index,row in enumerate(layout):
				for col_index, col in enumerate(row):
					if col != '-1':
						x = col_index * TILESIZE
						y = row_index * TILESIZE
						if style == 'boundary':
							Tile((x,y),[self.obstacle_sprites],'invisible')
						if style == 'grass':
							random_grass_image = choice(graphics['grass'])
							Tile((x,y),[self.visible_sprites, self.obstacle_sprites, self.attackable_sprites],'grass',random_grass_image)

						if style == 'object':
							surf = graphics['objects'][int(col)]
							Tile((x,y),[self.visible_sprites,self.obstacle_sprites],'object',surf)

						if style == 'entities':
							if col == '394':
								self.player = Player((x,y),[self.visible_sprites],self.obstacle_sprites,self.create_attack,self.destroy_attack,self.create_magic)
							else:
								if col == '390': monster_name = 'bamboo'
								elif col == '391': monster_name = 'spirit'
								elif col == '392': monster_name ='raccoon'
								else: monster_name = 'squid'
								Enemy(
									monster_name,
									(x,y),
									[self.visible_sprites,self.attackable_sprites],
									self.obstacle_sprites,
									self.damage_player,
									self.trigger_death_particles,
									self.add_exp)

	def add_exp(self,amount):
		self.player.exp += amount

	def create_magic(self,style,strength,cost):
		if style == 'heal':
			self.magic_player.heal(self.player,strength,cost,[self.visible_sprites])

		if style == 'flame':
			self.magic_player.flame(self.player,cost,[self.visible_sprites,self.attack_sprites])

	def create_attack(self):
		self.current_attack = Weapon(self.player,[self.visible_sprites, self.attack_sprites])

	def destroy_attack(self):
		if self.current_attack:
			self.current_attack.kill()
		self.current_attack = None

	def player_attack_logic(self):
		if self.attack_sprites:
			for attack_sprite in self.attack_sprites:
				collision_sprites = pygame.sprite.spritecollide(attack_sprite,self.attackable_sprites,False)
				if collision_sprites:
					for target_sprite in collision_sprites:
						if target_sprite.sprite_type == 'grass':
							pos = target_sprite.rect.center
							offset = pygame.math.Vector2(0,75)
							for leaf in range(randint(3,6)):
								self.animation_player.create_grass_particles(pos - offset,[self.visible_sprites])
							target_sprite.kill()
						else:
							target_sprite.get_damage(self.player,attack_sprite.sprite_type)

	def damage_player(self,amount,attack_type):
		if self.player.vulnerable:
			self.player.health -= amount
			if self.player.health <= 0:
				self.game_over = True
				return
			self.player.vulnerable = False
			self.player.hurt_time = pygame.time.get_ticks()
			self.animation_player.create_particles(attack_type,self.player.rect.center,[self.visible_sprites])

	def trigger_death_particles(self,pos,particle_type):
		self.animation_player.create_particles(particle_type,pos,self.visible_sprites)

	def toggle_menu(self):
		self.game_paused = not self.game_paused 

	def restart(self, mouse_pos):
		#如果点击区域在按钮区域内
		if self.button.rect.collidepoint(mouse_pos):
			#清空可见精灵组
			self.visible_sprites.empty()
			#清空障碍物精灵组
			self.obstacle_sprites.empty()
			#清空攻击目标精灵组
			self.attackable_sprites.empty()
			#从新加载地图数据
			self.create_map()
			#从新创建升级对象
			self.upgrade = Upgrade(self.player)
			#重置游戏结束标志
			self.game_over = False
		

	def run(self):
		self.visible_sprites.custom_draw(self.player)
		self.ui.display(self.player)
		
		if self.game_over:
			self.button.display()
		elif self.game_paused:
			#绘制升级菜单
			self.upgrade.display()
		else:
			#更新可见精灵组
			self.visible_sprites.update()
			self.visible_sprites.enemy_update(self.player)
			self.player_attack_logic()

class YSortCameraGroup(pygame.sprite.Group):
	def __init__(self):
		super().__init__()
		self.display_surface = pygame.display.get_surface()
		self.half_width = self.display_surface.get_size()[0] // 2
		self.half_height = self.display_surface.get_size()[1] // 2
		self.offset = pygame.math.Vector2()

		#加载背景图像
		self.floor_surf = pygame.image.load('../graphics/tilemap/ground.png').convert()
		#指定背景矩形对象左上角的位置
		self.floor_rect = self.floor_surf.get_rect(topleft = (0,0))

	def custom_draw(self,player):

		# 计算玩家与屏幕中心的偏移量
		self.offset.x = player.rect.centerx - self.half_width
		self.offset.y = player.rect.centery - self.half_height

		floor_offset_pos = self.floor_rect.topleft - self.offset
		self.display_surface.blit(self.floor_surf,floor_offset_pos)

		for sprite in sorted(self.sprites(),key = lambda sprite: sprite.rect.centery):
			#计算障碍精灵坐标
			offset_pos = sprite.rect.topleft - self.offset
			self.display_surface.blit(sprite.image,offset_pos)


	def enemy_update(self,player):
		enemy_sprites = [sprite for sprite in self.sprites() if hasattr(sprite,'sprite_type') and sprite.sprite_type == 'enemy']
		for enemy in enemy_sprites:
			enemy.enemy_update(player)
